//
// Created by sally on 24-10-27.
//

#ifndef TIMETASK_H
#define TIMETASK_H

#include <chrono>
#include <functional>
#include "TimerConfig.h"
#include "asyncthreadpool.hpp"

#define TIM_UNIT    50

namespace  whq::timer
{
    class AsyncThreadPool;

    /**
     *     这个类用来封装添加到时间轮中的任务，该任务的属性有:
     *     1、异步线程池句柄
     *     2、超时后需要执行的回调函数
     *     3、当前任务需要被执行的时间
     *     4、超时时间
     *     5、当前任务在五个时间轮上的位置，这样当任务快到期时，可以执行映射到当前位置，减少了映射时间
     *     6、需要记录当前处于哪个轮上
     *     7、总时间轮的开始时间
     *
     *
     *     这个类的函数：
     *     1、封装执行的函数；
     *     2、计算任务在每层时间轮上的索引；
     *     3、实现任务在时间轮上的映射，即从高时间轮跳转到低时间轮
     *
     */
    using Millseconds = std::chrono::milliseconds;
    using Callback_Function = std::function<bool(void)> ;
    using tmpoint = std::chrono::steady_clock::time_point;

    const Millseconds uint(TIM_UNIT);//这里的uint代表50毫秒了
    class TimeTask
    {

    public:
        explicit TimeTask(const Millseconds &millseconds,Callback_Function && Func,bool loop_cond,std::array<uint8_t, 5>&& cur_slots,
                          tmpoint epoch);
        ~TimeTask();

        //这是用来确定当前任务的层级的
        void init_task_level(const std::array<uint8_t, 5>& cur_slots);
        void execute();
        //获取任务执行的结果
        future<bool>& get_execute_result()
        {
            return m_future_bool;
        }

        // 这是循环任务时，这是根据之前的超时时间来重新生成每个层级的所在位置
        void do_loop(std::array<uint8_t, 5>&& cur_slots)
        {
            init_task_level(std::move(cur_slots));
        }

        bool isLoop() const {return is_loop;}

        //获取任务需要安装的时间槽
        std::pair<uint8_t,uint8_t> get_wheel_solt ();

        //这里是返回当前任务需要跳到的轮子序号和轮子的槽位
        std::pair<uint8_t,uint8_t> tick();
        uint32_t  get_loop_time() const {return m_time_out.count();}

    private:
        TimeTask(const TimeTask &)=delete;
        TimeTask(const TimeTask &&)=delete;
        TimeTask& operator =(const TimeTask &) = delete;
        TimeTask& operator =(const TimeTask &&) = delete;


    private:
        AsyncThreadPool& atp;       //异步线程池句柄
        Callback_Function   m_callback_function_;   //这是超时后的回调函数
        //当前任务需要被执行的时间
        tmpoint m_task_execute_point_;
        //任务的超时时长，即需要等待的时间
        Millseconds  m_time_out;
        //当任务添加时，需要首先确定其在五个时间轮中的位置值
        std::array<uint8_t, 5> m_slot_req;
        //记录当前处于哪个轮中
        uint8_t curwheel;
        tmpoint m_start_time;   //这是总时间轮的开始时间
        bool is_loop;
        future<bool>  m_future_bool;
        std::recursive_mutex       m_mutex_;        //递归锁
    };

}




#endif //TIMETASK_H
